﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
#if WINRT
using Windows.UI;
#else
using System.Windows.Media;
#endif

namespace Esponce.Common
{
	internal class Helper
	{
		#region JSON serialization
		/// <summary>
		/// Serializes object to JSON string.
		/// </summary>
		/// <param name="json">Object to be serialized.</param>
		/// <returns>Returns JSON string.</returns>
		/// <remarks>
		/// Serializable object should contain [DataContract] and [DataMember] attributes.
		/// </remarks>
		public static string JsonSerialize(object json)
		{
			using (var stream = new MemoryStream())
			{
				var serializer = new DataContractJsonSerializer(json.GetType());
				serializer.WriteObject(stream, json);
				stream.Position = 0;

				using (var reader = new StreamReader(stream, Encoding.UTF8))
				{
					return reader.ReadToEnd();
				}
			}
		}

		/// <summary>
		/// Deserializes JSON string to object.
		/// </summary>
		/// <typeparam name="T">Type of output object.</typeparam>
		/// <param name="json">JSON string to be deserialized.</param>
		/// <returns>Returns a new instance of T.</returns>
		/// <remarks>
		/// Serializable object should contain [DataContract] and [DataMember] attributes.
		/// </remarks>
		public static T JsonDeserialize<T>(string json)
		{
			using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
			{
				var serializer = new DataContractJsonSerializer(typeof(T));
				return (T)serializer.ReadObject(stream);
			}
		}
		#endregion

		#region XML serialization
		/// <summary>
		/// Serializes object to XML string.
		/// </summary>
		/// <param name="obj">Object to be serialized.</param>
		/// <returns>Returns XML string.</returns>
		/// <remarks>
		/// Serializable object should contain [DataContract] and [DataMember] attributes.
		/// </remarks>
		public static string XmlSerialize(object obj)
		{
			var serializer = new DataContractSerializer(obj.GetType());
			using (var stream = new MemoryStream())
			{
				serializer.WriteObject(stream, obj);
				byte[] data = stream.ToArray();
				string xml = Encoding.UTF8.GetString(data, 0, data.Length);
				return xml;
			}
		}

		/// <summary>
		/// Deserializes XML string to object.
		/// </summary>
		/// <typeparam name="T">Type of output object.</typeparam>
		/// <param name="xml">XML string be deserialized.</param>
		/// <returns>Returns a new instance of T.</returns>
		/// <remarks>
		/// Serializable object should contain [DataContract] and [DataMember] attributes.
		/// </remarks>
		public static T XmlDeserialize<T>(string xml)
		{
			var serializer = new DataContractSerializer(typeof(T));
			using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
			{
				var result = (T)serializer.ReadObject(stream);
				return result;
			}
		}
		#endregion

		#region Colors
		/// <summary>
		/// Converts web color to a System.Windows.Media.Color.
		/// </summary>
		/// <param name="hex"></param>
		/// <returns></returns>
		public static Color GetColor(string hex)
		{
			byte a = 0xFF, r = 0x00, g = 0x00, b = 0x00;

			if (string.IsNullOrEmpty(hex))
			{
				throw new ArgumentException("Input string is missing!");
			}

			if (hex[0] == '#')
			{
				hex = hex.Substring(1);
			}
			else
			{
				throw new ArgumentException("Expected hex color string starting with hash symbol!");
			}

			if (hex.Length == 8)
			{
				a = Convert.ToByte(hex.Substring(0, 2), 16);
				r = Convert.ToByte(hex.Substring(2, 2), 16);
				g = Convert.ToByte(hex.Substring(4, 2), 16);
				b = Convert.ToByte(hex.Substring(6, 2), 16);
			}
			else if (hex.Length == 6)
			{
				a = 0xFF;
				r = Convert.ToByte(hex.Substring(0, 2), 16);
				g = Convert.ToByte(hex.Substring(2, 2), 16);
				b = Convert.ToByte(hex.Substring(4, 2), 16);
			}
			else
			{
				throw new ArgumentException("Expected hex color string starting with 6 or 8 hex numbers!");
			}

			return Color.FromArgb(a, r, g, b);
		}

		public static bool TryGetColor(string hex, out Color color)
		{
			try
			{
				color = GetColor(hex);
				return true;
			}
			catch
			{
				color = Colors.Transparent;
				return false;
			}
		}
		#endregion
	}
}
